package MyFrame;

import dao.Player;
import dao.Point;
import tools.AIPlayer;
import tools.MusicPlayer;

import javax.imageio.ImageIO;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class ChessFrame extends JFrame implements MouseListener {
    private MusicPlayer bg=new MusicPlayer("music/chess_bg_mc.wav",true);
    int height=653,width=900;
    private int x,y;
    private int[][] chess = new int[19][19];
    private int round=0;
    private BufferedImage ChessBoard= null;
    private BufferedImage ChessBackground=null;
    private Thread bg_thread=null;
    private AIPlayer aiPlayer=new AIPlayer(chess,3);
    private Point p=null;
    private int judgeResult;
    private ChessFrame chessFrame=this;
    private PaintComponent pc=new PaintComponent();
    private int tempi=0,tempj=0;
    public ChessFrame()
    {
        this.round=0;
        this.setVisible(true);
        this.setTitle("五子棋");
        this.setFont(new Font("宋体",0,12));
        this.setSize(width,height);
        this.setResizable(false);
        int ScreenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;//获取屏幕高度
        int ScreenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;//获取屏幕宽度
        this.setLocation((ScreenWidth - width) / 2, (ScreenHeight - height) / 2);//设置窗口显示位置,由屏幕大小和窗口大小计算出中央坐标
        bg_thread=new Thread(bg);
        bg_thread.start();
        this.add(pc);//将绘图组件添加到窗体
        this.addMouseListener((MouseListener)this);
        try {
            ChessBoard = ImageIO.read(new File("images/chessboard.jpg"));
            ChessBackground = ImageIO.read(new File("images/chessBackground.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.addWindowListener(new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {

            }

            @Override
            public void windowClosing(WindowEvent e) {
            }

            @Override
            public void windowClosed(WindowEvent e) {
                System.out.println("窗口关闭");
            }

            @Override
            public void windowIconified(WindowEvent e) {

            }

            @Override
            public void windowDeiconified(WindowEvent e) {

            }

            @Override
            public void windowActivated(WindowEvent e) {

            }

            @Override
            public void windowDeactivated(WindowEvent e) {

            }
        });

    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        System.out.println("x:" + x);
        System.out.println("y:" + y);
        if (x >= 774 && x <= 868 && y >= 202 && y <= 241)//
        {

            bg_thread.stop();

            this.dispose();
        }//点击返回
        if (x >= 28 && x <= 649 && y >= 38 && y <= 635)//判断点击位置在棋盘范围内
        {
            //计算落子点在二维数组中的位置
            int i = (int) ((x - 30) * (18.00 / 610.00) + 0.3);
            int j = (int) ((y - 40) * (18.00 / 586.00) + 0.5);
            //如果这个点已经有棋子了就返回
            if (chess[i][j] != 0) return;
            //在该点存入玩家的黑棋，1代表黑棋，2代表白棋
            chess[i][j] = 1;
            //把玩家下的这步棋的位置传给AI
            aiPlayer.setTempx(i);
            aiPlayer.setTempy(j);
            //this.repaint();//重新绘制棋盘
            pc.paintImmediately(pc.getBounds());
            System.out.println((round + 1) + "打分情况为：" + aiPlayer.Evaluate(1));
            //更新回合
            round += 1;
            round %= 2;
            //根据这一步棋的位置判断输赢的结果
            int judgeResult = judgeWin(i, j);
            if (judgeResult == 0) //0表示任何一方都没有胜利
            {
                //AI方下棋
                p = aiPlayer.play();
                chess[p.getX()][p.getY()] = 2;
                tempi=p.getX();
                tempj=p.getY();
                System.out.println("AI下棋位置：i="+p.getY()+" j="+p.getX());
                System.out.println((round + 1) + "打分情况为：" + aiPlayer.Evaluate(1));
                pc.paintImmediately(pc.getBounds());
                judgeResult = judgeWin(i, j);
                round += 1;
                round %= 2;
            }
            if (judgeResult == 1)//1表示玩家黑棋胜利
            {
                MusicPlayer mp2 = new MusicPlayer("music/yabai.wav", false);
                Thread t = new Thread(mp2);
                t.start();
                JOptionPane.showMessageDialog(this, "黑棋胜利");
                try {
                    Win(1);//表示玩家获胜
                } catch (LineUnavailableException lineUnavailableException) {
                    lineUnavailableException.printStackTrace();
                } catch (UnsupportedAudioFileException unsupportedAudioFileException) {
                    unsupportedAudioFileException.printStackTrace();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }

            }
            if (p != null && judgeWin(p.getX(), p.getY()) == 2)//如果判断AI获胜
            {
                JOptionPane.showMessageDialog(this, "白棋胜利");
                try {
                    Win(2);//表示AI白棋获胜
                } catch (LineUnavailableException lineUnavailableException) {
                    lineUnavailableException.printStackTrace();
                } catch (UnsupportedAudioFileException unsupportedAudioFileException) {
                    unsupportedAudioFileException.printStackTrace();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }

        }

    }


    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent  e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
    public int judgeWin(int x,int y)
    {
        int front=0,rear=1;
        while(rear<19)
        {
            while(chess[front][y]==0&&rear<18)
            {
                front++;
                rear++;
            }
            if(chess[rear][y]!=chess[rear-1][y])
            {
                front=rear;
            }
            if(rear-front==4)
            {
                return chess[front][y];
            }
            rear++;
        }
        front=0;
        rear=1;
        while(rear<19)
        {
            while(chess[x][front]==0&&rear<18)
            {
                front++;
                rear++;
            }
            if(chess[x][rear]!=chess[x][rear-1])
            {
                front=rear;
            }
            if(rear-front==4)
            {
                return chess[x][front];
            }
            rear++;
        }
        int frontX=x>y?x-y:0;
        int frontY=x>y?0:y-x;
        int rearX=frontX+1,rearY=frontY+1;
        while(rearX<19&&rearY<19)
        {
            while(chess[frontX][frontY]==0&&rearX<18&&rearY<18)
            {
                frontX++;frontY++;rearX++;rearY++;
            }
            if(chess[rearX][rearY]!=chess[rearX-1][rearY-1])
            {
                frontX=rearX;
                frontY=rearY;
            }
            if(rearX-frontX==4)
            {
                return chess[frontX][frontY];
            }
            rearX++;rearY++;
        }


        frontX=x+y<19?0:x+y-18;
        frontY=x+y<19?x+y:18;
        rearX=frontX+1;
        rearY=frontY-1;
        while(rearX<19&&rearY>=0)
        {
            while(chess[frontX][frontY]==0&&rearX<18&&rearY>0)
            {
                frontX++;frontY--;rearX++;rearY--;
            }
            if(chess[rearX][rearY]!=chess[rearX-1][rearY+1])
            {
                frontX=rearX;
                frontY=rearY;
            }
            if(frontY-rearY==4)
            {

                return chess[frontX][frontY];
            }
            rearX++;rearY--;
        }
        return 0;
    }
    public void Win(int flag) throws LineUnavailableException, UnsupportedAudioFileException, IOException
    {
        if(flag==1)//表示玩家获胜
        {
            this.dispose();
            return;
        }
        int i,j,k;
        int result= JOptionPane.showConfirmDialog(this,"是否重新开始？");
        if(result==0)//重新开始
        {
            for(i=0;i<19;i++)
                for(j=0;j<19;j++)
                    chess[i][j]=0;
            round=0;
            this.aiPlayer.setFirstStep(true);
            this.repaint();
        }
        else//退出
        {

            this.dispose();
        }
    }

    class PaintComponent extends JComponent//绘图组件
    {
        public PaintComponent() {
            this.setFont(new Font("宋体",0,12));
            this.setSize(width,height);
        }

        @Override
        public void paint(Graphics g) {
            int i,j,k;
            int x,y;
            //采用双缓冲技术防止屏幕闪烁
            BufferedImage bi= new BufferedImage(height,width,BufferedImage.TYPE_INT_ARGB);
            Graphics g2=bi.createGraphics();//g2是bi缓冲层的画笔
            //先把背景绘制出来
            g.drawImage(ChessBackground,10,-10,this);
            //绘制棋盘图片到缓冲层
            g2.drawImage(ChessBoard,10,15,this);
            //设置样式
            g.setFont(new Font("宋体",0,25));
            g.setColor(Color.RED);
            //设定round==0的时候是黑方的回合，round==1的时候是白方的回合
            if(round==1) g.drawString("黑方回合",676,60);
            else g.drawString("白方回合",676,60);

            //在棋盘上把所有棋子都绘制出来，先绘制到缓冲层的棋盘上，全部绘制好之后再一起绘制到背景
            for(i=0;i<19;i++)
                for(j=0;j<19;j++)
                {
                    if(chess[i][j]==1)//绘制黑子
                    {
                        x= (int) (35+(float)i*(float)((float)610/(float)18));
                        y= (int) (44+(float)j*(float)((float)586/(float)18));
                        g2.setColor(Color.BLACK);
                        g2.fillOval(x-14,y-14,28,28);
                    }
                    if(chess[i][j]==2)//绘制白子
                    {
                        x= (int) (35+(float)i*(float)((float)610/(float)18));
                        y= (int) (44+(float)j*(float)((float)586/(float)18));
                        g2.setColor(Color.WHITE);
                        g2.fillOval(x-14,y-14,28,28);
                        g2.setColor(Color.BLACK);
                        g2.drawOval(x-14,y-14,28,28);
                    }
                }
            int tempX=(int) (35+(float)tempi*(float)((float)610/(float)18));
            int tempY= (int) (44+(float)tempj*(float)((float)586/(float)18));
            g2.setColor(Color.RED);
            g2.fillOval(tempX-4,tempY-4,8,8);
            //绘制缓冲层到窗体
            g.drawImage(bi,0,-30,this);

        }


    }
}
